package com.zy.shiro.service.Impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zy.shiro.domain.SysMenu;
import com.zy.shiro.domain.SysRoleMenu;
import com.zy.shiro.domain.SysUserRole;
import com.zy.shiro.mapper.SysMenuMapper;
import com.zy.shiro.mapper.SysRoleMenuMapper;
import com.zy.shiro.mapper.SysUserRoleMapper;
import com.zy.shiro.service.SysMenuService;
import com.zy.vo.Element;
import com.zy.vo.MenuAuthResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper,SysMenu> implements SysMenuService {

  @Autowired
  private SysUserRoleMapper sysUserRoleMapper;

  @Autowired
  private SysRoleMenuMapper sysRoleMenuMapper;

  @Autowired
  private SysMenuMapper sysMenuMapper;

//  @Autowired
//  private RedisTemplate redisTemplate;

  /**
   * 加载一个用户的菜单数据和权限数据
   * 认识表
   * user->role->menu
   * user_role  role_menu
   * 1 通过用户的id 查询用户所有的角色->List<Long> roleIds
   * 2 通过角色的id 查询菜单的id
   * 3 通过菜单的id 查询所有的菜单数据
   * 5 通过菜单数据拼接一个树结构
   *
   * @param userId
   * @return
   */
  @Override
  public MenuAuthResult loadMenuAndAuth(Long userId) {
    MenuAuthResult menuAuthResult = new MenuAuthResult();
    // 1 用户的id 查询角色
    List<Object> roleIds = sysUserRoleMapper.selectObjs(new LambdaQueryWrapper<SysUserRole>().select(
      SysUserRole::getRoleId
      ).
        eq(SysUserRole::getUserId, userId)
    );
    if (roleIds == null || roleIds.isEmpty()) {
      return menuAuthResult;
    }
    // 2 通过角色的id 查询菜单的id
    List<Object> menuIds = sysRoleMenuMapper.selectObjs(new LambdaQueryWrapper<SysRoleMenu>().select(
      SysRoleMenu::getMenuId
      ).in(SysRoleMenu::getRoleId, roleIds)
    );
    if (menuIds == null || menuIds.isEmpty()) {
      return menuAuthResult;
    }
    // 3 通过菜单的Id 查询菜单的数据
    List<SysMenu> sysMenus = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>().in(SysMenu::getMenuId, menuIds));
    if (sysMenus == null || sysMenus.isEmpty()) {
      return menuAuthResult;
    }
    // sysMenus 既有菜单，有url 地址就是菜单，还要权限，有perms 的就是权限
    Set<Element> elements = new HashSet<>(); // 它里面存放的是权限
    List<SysMenu> allMenuData = new ArrayList<>();
//    Set<String> permsCaches =new HashSet<>();//记录权限的,和Set《Elemet》有区别
    for (SysMenu sysMenu : sysMenus) {
      String perms = sysMenu.getPermisions();
      if (StringUtils.hasText(perms)) { // 权限的数据
        String[] permsArray = perms.split(",");
        for (int i = 0; i < permsArray.length; i++) {
          String s = permsArray[i];
//          permsCaches.add(s);
          elements.add(new Element(s)); // 现在set 集合里面是否能去重？可以，因为Element的equals的方法我重写；
        }
      }
      @NotNull Integer type = sysMenu.getMenuType();
      if (type.equals(0)||type.equals(1)){
        allMenuData.add(sysMenu);
      }
    }
//    redisTemplate.opsForValue().set("AUTH_PERMIS"+userId,permsCaches);
    menuAuthResult.setAuthorities(new ArrayList<>(elements));
    menuAuthResult.setMenuList(translateToTree(allMenuData));
    return menuAuthResult;
  }


@Override
public List<SysMenu> queryeMenuByUserIdForList(Long userId) {
    List<SysMenu> menuList=new ArrayList<>();
    List<Object> roleIds = sysUserRoleMapper.selectObjs(new LambdaQueryWrapper<SysUserRole>().select(
      SysUserRole::getRoleId
      ).
        eq(SysUserRole::getUserId, userId)
    );
    if (roleIds == null || roleIds.isEmpty()) {
      return menuList;
    }
    // 2 通过角色的id 查询菜单的id
    List<Object> menuIds = sysRoleMenuMapper.selectObjs(new LambdaQueryWrapper<SysRoleMenu>().select(
      SysRoleMenu::getMenuId
      ).in(SysRoleMenu::getRoleId, roleIds)
    );
    if (menuIds == null || menuIds.isEmpty()) {
      return menuList;
    }
    // 3 通过菜单的Id 查询菜单的数据
    List<SysMenu> sysMenus = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>()
//      .eq(SysMenu::getMenuType,0)
//      .eq(SysMenu::getMenuType,1)
      .in(SysMenu::getMenuId, menuIds));
  for (SysMenu sysMenu : sysMenus) {
    Integer menuType = sysMenu.getMenuType();
    if (menuType==0||menuType==1){
      menuList.add(sysMenu);
    }
  }
    if (sysMenus == null || sysMenus.isEmpty()) {
      return menuList;
    }


       return menuList;
  }

  /**
   * 把list 集合转换为一个菜单数据
   * @param sysMenus
   * @return
   */
  public List<SysMenu> translateToTree(List<SysMenu> sysMenus){
    List<SysMenu> root = new ArrayList<>();

    for (SysMenu sysMenu : sysMenus) {
      if(sysMenu.getParentId().equals(0L)){ // 父节点id= 0
        root.add(sysMenu) ;// 一级的节点
      }
    }

    for (SysMenu sysMenu : root) { // 所有的一级节点
      List<SysMenu> subNodes = new ArrayList<>();
      for (SysMenu menu : sysMenus) {
        // 父亲== 我
        if(menu.getParentId().equals(sysMenu.getMenuId())){
          subNodes.add(menu);
        }
      }
      sysMenu.setList(subNodes); // 把所有的儿子放在里面
    }
    return  root  ;
  }
}
